﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System;
using System.Security.Cryptography;

public class BuildBundle
{
    static string BundleDirectory = Application.dataPath + "/Bundle";
    static string BaseBundleOutput = Application.streamingAssetsPath + "/";
    static string Version;
    static string BundleOutput;
  
    [MenuItem("Bundle/Android")]
    static void BuildAndroid()
    {
        AndroidRes();
    }

    static void AndroidRes(){
        try
        {
            EditorUtility.DisplayProgressBar("安卓Bundle进度", "正在打Android资源包...", 0);

            ClearAssetsName();

            if (!SetAssetsName())
            {
                EditorUtility.ClearProgressBar();
                return;
            }

            CreateVersion(BuildTarget.Android);

            EditorUtility.DisplayProgressBar("安卓Bundle进度", "正在打Android资源包...", 0.1f);

            StartBuild(BuildTarget.Android);
            EditorUtility.DisplayProgressBar("安卓Bundle进度", "正在打Android资源包...", 0.9f);

            ClearAssetsName();
            EditorUtility.DisplayProgressBar("安卓Bundle进度", "正在打Android资源包...", 1.0f);

            AssetDatabase.SaveAssets();
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
            EditorUtility.DisplayDialog("提示", "Bundle打包成功", "确定");
        }
        catch (System.Exception e)
        {
            EditorUtility.ClearProgressBar();
            Debug.LogError(e.ToString());
            throw;
        }
    }

    static void ClearAssetsName()
    {
        string[] abNames = AssetDatabase.GetAllAssetBundleNames();
        foreach (string name in abNames)
        {
            AssetDatabase.RemoveAssetBundleName(name, true);
        }
    }

    static bool SetAssetsName()
    {
        DirectoryInfo[] directorys = FileTools.GetDirectorys(BundleDirectory);
        foreach (DirectoryInfo di in directorys)
        {
            FileInfo[] files = FileTools.GetFiles(di.FullName, SearchOption.AllDirectories);
            if (CheckSameName(files))
            {
                return false;
            }
            foreach (FileInfo file in files)
            {
                if (file.Extension.Equals(".meta")) continue;
                string assetpath = AssetTools.GetAssetPath(file.FullName);
                AssetImporter asset = AssetImporter.GetAtPath(assetpath);
                asset.assetBundleName = di.Name;
                Debug.Log("---:" + asset.assetBundleName);
                asset.assetBundleVariant = string.Empty;

            }
        }
        AssetDatabase.Refresh();
        return true;
    }

    static void StartBuild(BuildTarget target)
    {
        if (Directory.Exists(Application.streamingAssetsPath))
        {
            Directory.Delete(Application.streamingAssetsPath, true);
        }
        else
        {
            Directory.CreateDirectory(Application.streamingAssetsPath);
        }

        AssetTools.ClearConsole();
        string tempCachePath = Application.streamingAssetsPath + "/" + "tempPath";
        if (!Directory.Exists(tempCachePath))
        {
            Directory.CreateDirectory(tempCachePath);
        }

        AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(tempCachePath, BuildAssetBundleOptions.ChunkBasedCompression, target);
        DirectoryInfo[] directorys = FileTools.GetDirectorys(BundleDirectory);
        BundleInfos bundles = new BundleInfos();
        string output = BaseBundleOutput + Version + "/";
        if (!Directory.Exists(output))
        {
            Directory.CreateDirectory(output);
        }
        foreach (DirectoryInfo di in directorys)
        {
            if (!File.Exists(tempCachePath + "/" + di.Name)) continue;
            BundleInfo bundle = new BundleInfo();
            bundle.name = di.Name;
            bundle.md5 = manifest.GetAssetBundleHash(di.Name).ToString();

            FileInfo info = new FileInfo(tempCachePath + "/" + bundle.name);
            info.CopyTo(output + bundle.name);
            bundle.size = info.Length;
            bundles.bundles.Add(bundle);
        }
        bundles.version = Version;
        string json = JsonUtility.ToJson(bundles);
        File.WriteAllText(Application.streamingAssetsPath + "/bundleversion.txt", json);

        Directory.Delete(tempCachePath, true);
    }

    static void UploadOSS()
    {

    }

    static bool CheckSameName(FileInfo[] files)
    {
        for (int index = 0; index < files.Length - 1; index++)
        {
            for (int j = index + 1; j < files.Length; j++)
            {
                if (files[index].Name.Equals(files[j].Name))
                {
                    Debug.LogError("Bundle失败,文件同名 " + files[index].FullName + "," + files[j].FullName);
                    return true;
                }
            }
        }
        return false;
    }

    static void CreateVersion(BuildTarget target)
    {
        if (target == BuildTarget.StandaloneWindows64)
        {
            Version = "editorbundle";
        }
        else
        {
            DateTime dt = DateTime.Now;
            Version = dt.ToString("yyyy-MM-dd_HH-mm-ss");
        }
        string output = BaseBundleOutput + Version;
        if (Directory.Exists(output))
        {
            Directory.Delete(output, true);
        }
        Directory.CreateDirectory(output);
    }

    public static String BuildFileMd5(String path)
    {
        String filemd5 = null;
        try
        {
            using (var fileStream = File.OpenRead(path))
            {
                var md5 = MD5.Create();
                var fileMD5Bytes = md5.ComputeHash(fileStream);//计算指定Stream 对象的哈希值                                     
                filemd5 = FormatMD5(fileMD5Bytes);
            }
        }
        catch (System.Exception ex)
        {
            Debug.Log(ex.ToString());
        }
        return filemd5;
    }

    public static string FormatMD5(Byte[] data)
    {
        return System.BitConverter.ToString(data).Replace("-", "").ToLower();//将byte[]装换成字符串
    }

}


[System.Serializable]
public class BundleInfo
{
    public string name;
    public string md5;
    public long size;
}



[System.Serializable]
public class BundleInfos
{
    public string version;
    public List<BundleInfo> bundles = new List<BundleInfo>();
}
